/*
 * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-04-28     CDT          first version
 * 2024-06-07     CDT          Modify the IRQ install implementation for F448/F472
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include <rtthread.h>
#include "drv_irq.h"

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/
/**
 * @brief Function pointer type to void/void function
 */
typedef void (*func_ptr_t)(void);

/**
 * @brief  Interrupt registration structure definition
 */
typedef struct {
    en_int_src_t enIntSrc;  /*!< Peripheral interrupt number, can be any value @ref en_int_src_t    */
    IRQn_Type enIRQn;       /*!< Peripheral IRQ type, can be INT000_IRQn~INT127_IRQn @ref IRQn_Type */
    func_ptr_t pfnCallback; /*!< Callback function for corresponding peripheral IRQ                 */
} stc_irq_signin_config_t;
/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
#if defined (HC32F448) || defined (HC32F472)
    /* Interrupt registration max number */
    #define HC32_INT_REG_MAX_NUM        (16U)
#endif

/**
 * @defgroup Generic_Error_Codes Generic Error Codes
 * @{
 */
#define LL_OK                           (0)   /*!< No error */
#define LL_ERR                          (-1)  /*!< Non-specific error code */
#define LL_ERR_UNINIT                   (-2)  /*!< Module (or part of it) was not initialized properly */
#define LL_ERR_INVD_PARAM               (-3)  /*!< Provided parameter is not valid */
#define LL_ERR_INVD_MD                  (-4)  /*!< Operation not allowed in current mode */
#define LL_ERR_NOT_RDY                  (-5)  /*!< A requested final state is not reached */
#define LL_ERR_BUSY                     (-6)  /*!< A conflicting or requested operation is still in progress */
#define LL_ERR_ADDR_ALIGN               (-7)  /*!< Address alignment does not match */
#define LL_ERR_TIMEOUT                  (-8)  /*!< Time Out error occurred (e.g. I2C arbitration lost, Flash time-out, etc.) */
#define LL_ERR_BUF_EMPTY                (-9)  /*!< Circular buffer can not be read because the buffer is empty */
#define LL_ERR_BUF_FULL                 (-10) /*!< Circular buffer can not be written because the buffer is full */

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
rt_err_t hc32_install_irq_handler(struct hc32_irq_config *irq_config,
                                  void (*irq_hdr)(void),
                                  rt_bool_t irq_enable)
{
    rt_err_t result = -RT_ERROR;
    stc_irq_signin_config_t stcIrqSignConfig;

    RT_ASSERT(RT_NULL != irq_config);


    stcIrqSignConfig.enIRQn      = irq_config->irq_num;
    stcIrqSignConfig.enIntSrc    = irq_config->int_src;
    stcIrqSignConfig.pfnCallback = irq_hdr;
    if (LL_OK == INTC_IrqSignIn(&stcIrqSignConfig))
    {
        NVIC_ClearPendingIRQ(irq_config->irq_num);
        NVIC_SetPriority(irq_config->irq_num, irq_config->irq_prio);
        if (RT_TRUE == irq_enable)
        {
            NVIC_EnableIRQ(irq_config->irq_num);
        }
        else
        {
            NVIC_DisableIRQ(irq_config->irq_num);
        }
        result = RT_EOK;
    }

    return result;
}

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
